package com.mobile.framework.action;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;

import com.mobile.framework.exception.BaseException;
import com.mobile.framework.exception.SystemException;

/**
 * 在Strust中定制异常的处理
 */
public class CustomExceptionHandler extends ExceptionHandler {
	private Log log = LogFactory.getLog(getClass().getName());

	@Override
	public ActionForward execute(Exception ex, ExceptionConfig ae,
			ActionMapping mapping, ActionForm formInstance,
			HttpServletRequest request, HttpServletResponse response)
			throws ServletException {
		log.error("Handle Exception:" + ex.getMessage(), ex);
		ActionForward forward = null;
		ActionMessage error = null;
		String property = null;

		if (ae.getPath() != null) {
			forward = new ActionForward(ae.getPath());
		} else {
			forward = mapping.getInputForward();
		}

		/*
		 * Figure out what type of exception has been thrown. The Struts
		 * AppException is not being used in this example.
		 */
		if (ex instanceof BaseException) {
			// This is the specialized behavior
			BaseException baseException = (BaseException) ex;
			String messageKey = baseException.getMessageKey();
			Object[] exArgs = baseException.getMessageArgs();
			if (exArgs != null && exArgs.length > 0) {
				// If there were args provided, use them in the ActionError
				error = new ActionMessage(messageKey, exArgs);
			} else {
				// Create an ActionError without any arguments
				error = new ActionMessage(messageKey);
			}
		} else if (ex instanceof DataAccessException) {
			BaseException baseException = convertDataAccessException((DataAccessException) ex);
			String messageKey = baseException.getMessageKey();
			error = new ActionMessage(messageKey);
		} else {
			error = new ActionMessage("系统错误！错误根源：{0}  <br>请与系统管理员联系！", ex.getMessage());

		}
		property = error.getKey();
		request.setAttribute(Globals.EXCEPTION_KEY, ex);
		// Store the ActionError into the proper scope
		// The storeException method is defined in the parent class
		storeException(request, property, error, forward, ae.getScope());

		return forward;
	}
	
	private BaseException convertDataAccessException(DataAccessException e) {
		if (e instanceof DataAccessResourceFailureException) {
			return new SystemException("数据库连接失败");
		} else if (e instanceof DataIntegrityViolationException) {
			return new SystemException("数据为更新操作不完整");
		} else if (e instanceof DataRetrievalFailureException) {
			return new SystemException("数据访问层找不到此实体对象");
		} else if (e instanceof InvalidDataAccessResourceUsageException) {
			return new SystemException("数据访问层SQL语句错误");
		} else {
			return new SystemException("数据访问层操作失败");
		}
	}
}